package logic

import (
	"fmt"
	"gopkg.in/mgo.v2/bson"
	"svvenus/conf"
	"svvenus/util/uttype"
	"svvenus/vgame/model"
	"svvenus/vpub/constants"
	"svvenus/vpub/db/dbm"
	"svvenus/zlog"
)

// Save
// @Description: 存档
// @receiver player
// @param db
// @param isNew是否新存
func (player *Player) Save(db *dbm.MgoSession, isNew bool) bool {
	player.SavePrepare()

	var err error
	//基础数据
	err = db.Save(&player.PlayerDoc, isNew)
	if err != nil {
		zlog.Error(err)
		return false

	}
	//邮件
	for _, v := range player.Mails {
		v.Save(db)
	}
	//装备
	for _, v := range player.Equips {
		v.Save(db)
	}
	return true
}

// SaveMe
// @Description: 存档
// @receiver player
func (player *Player) SaveMe() {
	db := constants.MgoMain.New()
	defer db.Close()
	player.Save(db, false)
}

func (player *Player) Load() bool {
	db := constants.MgoMain.New()
	defer db.Close()

	err := db.GetId(&player.PlayerDoc)
	if err != nil {
		zlog.Error(fmt.Sprintf("玩家读档失败 基础 pid=%s", player.IdString()), err)
		return false
	}
	//邮件
	{
		newIds := make([]string, 0)
		player.Mails = make(map[string]*Mail)
		for _, v := range player.MailIds {
			mail := &Mail{}
			mail.Id = bson.ObjectIdHex(v)
			mail.Pid = player.IdString()
			if mail.Load(db) {
				player.Mails[mail.IdString()] = mail
				newIds = append(newIds, v)
			}
		}
		player.MailIds = newIds
	}
	//装备
	{
		newIds := make([]string, 0)
		player.Equips = make(map[string]*Equip)
		for _, v := range player.EquipIds {
			equip := &Equip{}
			equip.Id = bson.ObjectIdHex(v)
			equip.Pid = player.IdString()
			if equip.Load(db) {
				player.Equips[equip.IdString()] = equip
				newIds = append(newIds, v)
			}
		}
		player.EquipIds = newIds
	}

	player.LoadAfter()
	return true
}

// SavePrepare
// @Description: 存档前处理
// @receiver player
func (player *Player) SavePrepare() {
	player.MailIds = make([]string, 0)
	for k, _ := range player.Mails {
		player.MailIds = append(player.MailIds, k)
	}
	player.EquipIds = make([]string, 0)
	for k, _ := range player.Equips {
		player.EquipIds = append(player.EquipIds, k)
	}
}

// LoadAfter
// @Description: 读档后处理
// @receiver player
func (player *Player) LoadAfter() {
}

// PlayerGet 玩家获取
// @param pid
// @param mode
// @return *model.Player
func PlayerGet(pid string, mode PlayerDataGetMode) *Player {
	v, ok := MapPlayer.Load(pid)
	if ok {
		return v.(*Player)
	}
	if mode == PlayerDataGetModeAll {
		player := &Player{}
		if !bson.IsObjectIdHex(pid) {
			return nil
		}
		player.Id = bson.ObjectIdHex(pid)
		if player.Load() {
			return player
		}
	}
	return nil
}

// PlayerGetPidFormUserId
// @Description: 根据UserId查找Pid
// @param userId
// @return string
// @return bool
func PlayerGetPidFormUserId(userId string) (string, bool) {
	db := constants.MgoMain.New()
	defer db.Close()

	return db.FindKey(model.PlayerCollectionName, bson.M{"UserId": userId})
}

// PlayerGetPidFormName
// @Description:
// @param name
// @return string
// @return bool
func PlayerGetPidFormName(name string) (string, bool) {
	db := constants.MgoMain.New()
	defer db.Close()

	return db.FindKey(model.PlayerCollectionName, bson.M{"Name": name})
}

// PlayerSaveAll 存盘所有玩家
func PlayerSaveAll() {
	db := constants.MgoMain.New()
	defer db.Close()
	MapPlayer.Range(func(k, v interface{}) bool {
		p := v.(*Player)
		p.Save(db, false)
		return true
	})
	zlog.Info("所有玩家存档 end .............")
}

// PlayerCheckName
// @Description: 判断名字
// @param name
// @return int32
func PlayerCheckName(name string) uint16 {
	if len(name) < conf.GlobalGetInt(conf.EGlobalId昵称长度最小) {
		return conf.EProtocolResult名字长度太短
	}
	if len(name) > conf.GlobalGetInt(conf.EGlobalId昵称长度最大) {
		return conf.EProtocolResult名字长度太长
	}
	if uttype.SliceStringHas(conf.ListNameBad, name) {
		return conf.EProtocolResult名字含有不合法或者不雅字符
	}

	db := constants.MgoMain.New()
	defer db.Close()
	count, err := db.Count(model.PlayerCollectionName, bson.M{"Name": name})
	if err != nil {
		return conf.EProtocolResult服务器数据库异常
	}
	if count > 0 {
		return conf.EProtocolResult名字已经被使用
	}
	return 0
}
